/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lisp;

/**
 *
 * @author luisorozco
 */

import java.util.LinkedList;
import java.util.HashMap;
import java.util.Queue;
import java.util.TreeMap;
import java.text.NumberFormat;
import java.util.ArrayList;

public class Listas {
        
        
        private ArrayList<String> aritmeticas;
        private ArrayList<String> condiciones;
        private ArrayList<String> otras;
        private ArrayList<String> funciones;
        private HashMap<String, String> therap;
        private  static Funciones funcion;
        
        public Listas()
        {
                aritmeticas=new ArrayList<String>();
                aritmeticas.add("+");
                aritmeticas.add("-");
                aritmeticas.add("*");
                aritmeticas.add("/");
                
                condiciones=new ArrayList<String>();
                condiciones.add("<");
                condiciones.add("¬"); //mrnor igual
                condiciones.add("&"); 
                condiciones.add("=");
                condiciones.add(">");
                
                otras=new ArrayList<String>();
                otras.add("setf"); 
                
                funciones=new ArrayList<String>();
                
                therap = new HashMap<String,String>();
                
                funcion=new Funciones(this);
        }
        
        public String Operar(String input)
        {
                boolean hacerCond=false;
                double resultadoNumero=0;
                boolean resultadoCondicional=true;
                boolean resultado_set=false;
                String resultadoS="";
                
                Queue<String> pila_operandos= new LinkedList<String>();
                Queue<String> pila_operadores= new LinkedList<String>();
                
                input=input.substring(1, input.length());
                
                
                for(int i=0; i<funciones.size(); i++)
                {
                        String funcN=funciones.get(i);
                        if(input.contains(funcN))
                        {
                                resultadoS=funcion.OperarFun(input);
                                return resultadoS;
                        }
                }
                
               
                if(input.contains("setf"))
                {
                        int buffer=input.indexOf(' ');
                        input="s"+input.substring(buffer, input.length());
                }
                if(input.contains("<=") || input.contains(">=") || input.contains("EQUAL"))
                {
                        String source="";
                        if(input.contains("<=")) source="¬";
                        if(input.contains(">=")) source="&";
                        if(input.contains("EQUAL")) source="=";
                        
                        int buffer=input.indexOf(' ');
                        input=source+input.substring(buffer, input.length());
                }
                
              
                for(int i=0; i<input.length(); i++)
                {
                        char c=input.charAt(i);
                        
                        if(c==')')
                        {
                                String pop1=pila_operadores.poll();
                                
                                if(condiciones.contains(pop1))
                                {
                                        hacerCond=true;
                                }
                                
                                while(!pila_operandos.isEmpty()){
                                        
                                        String pop2=setTherap1(pila_operandos.poll());
                                        
                                        if(otras.contains(pop1))
                                        {
                                                String pop2a=pila_operandos.poll();
                                                setTherap2(pop2, pop2a);
                                                resultadoS=pop2a;
                                        }
                                        else if(condiciones.contains(pop1))
                                        {
                                                String pop2a=setTherap1(pila_operandos.poll());
                                                resultadoCondicional=resultadoCondicional && funcionesCond(Double.parseDouble(pop2),Double.parseDouble(pop2a), pop1.charAt(0));
                                                resultadoS=""+resultadoCondicional+"";
                                                
                                                if(resultadoS.compareTo("true")==0||resultadoS.compareTo("false")==0)
                                                {
                                                        if(resultadoS.compareTo("true")==0)
                                                        {
                                                                resultadoS="True";
                                                        }
                                                        else 
                                                        {
                                                                resultadoS="NIL";
                                                        }
                                                }
                                                
                                        }
                                        else if(aritmeticas.contains(pop1))
                                        {       
                                                if(!resultado_set)
                                                {
                                                        resultadoNumero=Double.parseDouble(pop2);
                                                        resultado_set=true;
                                                }
                                                else {
                                                        resultadoNumero=funcionesArit(resultadoNumero,Double.parseDouble(pop2),pop1.charAt(0));
                                                        resultadoS=""+resultadoNumero+"";
                                                }
                                        }
                                }
                                hacerCond=false;
                                resultado_set=false;
                                return resultadoS;
                        }
                        else if(c=='(')
                        {
                                input=input.substring(i);
                                pila_operandos.add(""+Operar(input)+"");
                                input=input.substring(input.indexOf(')'));
                                i=0;
                        }
                        else if(aritmeticas.contains(""+c+"") || condiciones.contains(""+c+"") || otras.contains(""+c+""))
                        {
                                if(c=='*') resultadoNumero=1;

                                pila_operadores.add(""+c+"");
                        }
                        else if(c!=' ')
                        {
                                String operando="";
                                
                                while(c!=' ' && c!='(' && c!=')'){

                                        operando=operando+c;
                                        i++;
                                        c=input.charAt(i);      
                                }

                                pila_operandos.add(operando);
                                i--;
                        }
                }
                return null;
        }

        public double funcionesArit(double x, double y, char o)
        {
                if(o=='+')
                {
                        return x+y;
                }
                if(o=='*')
                {
                        return x*y;
                }
                if(o=='-')
                {
                        return x-y;
                }
                if(o=='/')
                {
                        return x/y;
                }
                return 0;
        }
        
        public boolean funcionesCond(double x, double y, char o)
        {
                        
                if(o=='<')
                {
                        return x<y;
                }
                if(o=='>')
                {
                        return x>y;
                }
                if(o=='=')
                {
                        return x==y;
                }
                if(o=='¬')
                {
                        return x<=y; 
                }
                if(o=='&')
                {
                        return x>=y;
                }
                
                return false;
        }

        public boolean evaluarCOND(String input)
        {
                return false;
        }
        
        public String setTherap1(String input)
        {       
                if(therap.containsKey(input))
                {
                        return therap.get(input);
                }
                return input;
        }
        
        public void setTherap2(String key, String valor)
        {
                therap.put(key, valor);
        }

}